package top.yangyitao.lockManager.lock.zookeeper;

import top.yangyitao.lockManager.lock.LockSubject;
import top.yangyitao.lockManager.zookeeper.CuratorFrameworkBuilder;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author eetal
 */
public class ZookeeperLockSubject extends LockSubject<Object> {
    private final static String lockPrefix = "/lock/";
    private static Map<String, InterProcessMutex> zookeeperSyncLockMap = new ConcurrentHashMap<String, InterProcessMutex>();

    private boolean alive = false;
    private String sync;//Object.toString().intern()

    private InterProcessMutex interProcessMutex;

    protected ZookeeperLockSubject(){}

    @Override
    public void initialize(Object obj) {
        String _sync = obj.toString().intern();
        sync = _sync;
        synchronized (_sync) {
            if (zookeeperSyncLockMap.containsKey(_sync)) {
                interProcessMutex = zookeeperSyncLockMap.get(_sync);
            } else {
                interProcessMutex = new InterProcessMutex(CuratorFrameworkBuilder.getInstance(),lockPrefix+_sync);
            }
            zookeeperSyncLockMap.put(_sync, interProcessMutex);//防止刚好别的线程解锁完
            alive = true;
        }
    }

    @Override
    public void destroy() {
        sync = null;
        interProcessMutex = null;
        alive = false;
    }

    @Override
    public boolean isHeldByCurrentThread() {
        return interProcessMutex == null?false:interProcessMutex.isOwnedByCurrentThread();
    }

    @Override
    public void lock() {
        try {
            if(!interProcessMutex.acquire(3500,TimeUnit.MILLISECONDS)){
                throw new RuntimeException("获取锁失败");
            }
        }catch (Exception e){
            throw new RuntimeException("获取锁失败");
        }
    }

    @Override
    public void tryLock() {
        try {
            if(!interProcessMutex.acquire(3500,TimeUnit.MILLISECONDS)){
                throw new RuntimeException("获取锁失败");
            }
        }catch (Exception e){
            throw new RuntimeException("获取锁失败");
        }
    }

    @Override
    public void unlock() {
        try {
            interProcessMutex.release();
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public boolean equalKey(Object o) {
        return sync.equals(o);
    }

    @Override
    public boolean isAlive() {
        return alive;
    }
}
